#include <Wire.h>

#define DS3231_ADDRESS 0x68

void setup() {
  Serial.begin(9600);
  Wire.begin();

  // 设置 DS3231 的时间，格式为年、月、日、时、分、秒
  setDateTime(2022, 1, 1, 12, 0, 0);

  Serial.println("Time set!");
}

void loop() {
  // 读取 DS3231 的时间
  int year, month, day, hour, minute, second;
  getDateTime(year, month, day, hour, minute, second);

  // 将 DS3231 的时间打印到串口监视器
  Serial.print("Year: ");
  Serial.print(year);
  Serial.print(" Month: ");
  Serial.print(month);
  Serial.print(" Day: ");
  Serial.print(day);
  Serial.print(" Hour: ");
  Serial.print(hour);
  Serial.print(" Minute: ");
  Serial.print(minute);
  Serial.print(" Second: ");
  Serial.println(second);

  delay(1000);
}

void setDateTime(int year, int month, int day, int hour, int minute, int second) {
  Wire.beginTransmission(DS3231_ADDRESS);
  Wire.write(0); // 设置寄存器为秒寄存器
  Wire.write(decToBcd(second)); // 将秒转换为 BCD 格式并写入寄存器
  Wire.write(decToBcd(minute)); // 将分钟转换为 BCD 格式并写入寄存器
  Wire.write(decToBcd(hour)); // 将小时转换为 BCD 格式并写入寄存器
  Wire.write(decToBcd(0)); // 设置星期几为 0（未使用）
  Wire.write(decToBcd(day)); // 将日期转换为 BCD 格式并写入寄存器
  Wire.write(decToBcd(month)); // 将月份转换为 BCD 格式并写入寄存器
  Wire.write(decToBcd(year - 2000)); // 将年份转换为 BCD 格式并写入寄存器
  Wire.endTransmission();
}

void getDateTime(int &year, int &month, int &day, int &hour, int &minute, int &second) {
  Wire.beginTransmission(DS3231_ADDRESS);
  Wire.write(0); // 设置寄存器为秒寄存器
  Wire.endTransmission(false);
  Wire.requestFrom(DS3231_ADDRESS, 7); // 读取 7 个字节的数据

  second = bcdToDec(Wire.read() & 0x7F); // 读取秒，并将最高位的 CH 位清零
  minute = bcdToDec(Wire.read());
  hour = bcdToDec(Wire.read() & 0x3F); // 读取小时，并将最高位的 12/24 位清零
  Wire.read(); // 读取星期几，但未使用
  day = bcdToDec(Wire.read());
  month = bcdToDec(Wire.read());
  year = 2000 + bcdToDec(Wire.read());
}

byte decToBcd(byte value) {
  return ((value / 10) << 4) + (value % 10);
}

byte bcdToDec(byte value) {
  return ((value >> 4) * 10) + (value & 0x0F);
}